<template>
	<div class="code-editor" :style="{'height':_height}" style="width:100%">
		<textarea ref="textarea" v-model="contentValue" class="CodeMirror-hints" style="white-space:pre-line"></textarea>
	</div>
</template>

<script>
	import { markRaw } from "vue"

	//框架
	import CodeMirror from 'codemirror'
	import 'codemirror/lib/codemirror'
	import 'codemirror/lib/codemirror.css'
	import 'codemirror/theme/solarized.css'

	//主题
	
	import 'codemirror/theme/dracula.css'
	import 'codemirror/theme/idea.css'

	import "codemirror/theme/panda-syntax.css"
	import "codemirror/theme/ambiance.css"
	import "codemirror/addon/hint/show-hint.css"

	//功能
	import 'codemirror/addon/selection/active-line'

	//语言
	import 'codemirror/mode/javascript/javascript'
	import 'codemirror/mode/sql/sql'

	//提示
	import 'codemirror/addon/edit/closebrackets.js'
	import 'codemirror/addon/hint/show-hint.js'
	import 'codemirror/mode/sql/sql.js'
	import 'codemirror/addon/display/autorefresh'
	import 'codemirror/addon/hint/sql-hint.js'
	import 'codemirror/addon/hint/javascript-hint.js'

	export default {
		props: {
			modelValue: {
				type: String,
				default: ""
			},
			mode: {
				type: String,
				default: "javascript"
			},
			height: {
				type: [String,Number],
				default: 300,
			},
			options: {
				type: Object,
				default: () => {}
			},
			theme: {
				type: String,
				default: "idea"
			},
			readOnly: {
				type: Boolean,
				default: false
			},
		},
		data() {
			return {
				contentValue: this.modelValue,
				coder: null,
				opt: {
					theme: this.theme,	//主题
					styleActiveLine: true,	//高亮当前行
					lineNumbers: true,	//行号
					lineWrapping: true,	//自动换行
					tabSize: 4,	//Tab缩进
					matchBrackets: true, //括号匹配
					indentUnit: 4,	//缩进单位
					indentWithTabs : true,	//自动缩进
					mode : this.mode,	//语言
					readOnly: this.readOnly,	//只读

					mode: 'text/x-sql',
					line: true,
					autoCloseBrackets: true, // 在键入时自动关闭括号和引号
					autoRefresh: true,
					smartIndent: true,
					lineWrapping: true, // 是否应滚动或换行以显示长行
					hintOptions: {
						completeSingle: false,
						hint: this.handleShowHint,
					},
					...this.options
				},
			}
		},
		computed: {
			_height() {
				return Number(this.height)?Number(this.height)+'px':this.height
			},
		},
		watch: {
			modelValue(val) {
				this.contentValue = val
				if (val !== this.coder.getValue()) {
					this.coder.setValue(val)
				}
			},
		},
		mounted() {
			this.init()
		},
		methods: {
			init(){
				this.$nextTick(()=>{
					this.coder = markRaw(CodeMirror.fromTextArea(this.$refs.textarea, this.opt))
					this.coder.on('change', (coder) => {
						this.contentValue = coder.getValue()
						this.$emit('update:modelValue', this.contentValue)
					})
					// 代码提示功能 当用户有输入时，显示提示信息
					this.coder.on("inputRead", (cm) => {
						cm.showHint();
					});
				})
			},
			formatStrInJson(strValue) {
				return JSON.stringify(JSON.parse(strValue), null, 4)
			},
			setVariables(variables){
				let pos1 = this.coder.getCursor();
				let pos2 = {};
				pos2.line = pos1.line;
				pos2.ch = pos1.ch;
				this.coder.replaceRange(variables,pos2);
				// let cursor = cmInstance.getCursor();
				// let cursorLine = cmInstance.getLine(cursor.line);
				// let end = cursor.ch;
				// let start = end;

				// let token = cmInstance.getTokenAt(cursor)
				// return {
				// 	list: variables,
				// 	from: {ch: token.start, line: cursor.line},
				// 	to: {ch: token.end, line: cursor.line}
				// };
			},
			// 对应按键下调用的自动提示方法
			completeAfter(cm, pred) {
				console.log('asdasd')
				if (!pred || pred()) {
					console.log('A')
					setTimeout(function() {
						if (!cm.state.completionActive) {
							cm.showHint({
								completeSingle: false
							})
						}
					}, 100)
				}
				return CodeMirror.Pass
    		},
			// 代码自动提示
			handleShowHint(cmInstance, hintOptions) {
				let cursor = cmInstance.getCursor();
				let cursorLine = cmInstance.getLine(cursor.line);
				let end = cursor.ch;
				let start = end;

				let token = cmInstance.getTokenAt(cursor)
				return {
					//list:["SYS_USER_ID","SYS_USER_NAME","SYS_USER_ACCOUNT","SYS_USER_MOBILE","SYS_DEP_ID","SYS_DEP_NAME","SYS_APPLY_DATE","SYS_APPLY_NO"],
					list:[
						{
							text: "abcd",
							displayText: "abcd",
							displayInfo: "提示信息1",
							render: this.hintRender
						}, 
						{
							text: "qwer",
							displayText: "qwer",
							displayInfo: "提示信息2",
							render: this.hintRender
							}
						],
					from: {ch: token.start, line: cursor.line},
					to: {ch: token.end, line: cursor.line}
				};
			},
			 // 提示框显示及样式
			 hintRender(element, self, data) {
				console.log('AAAAA', data)
				let div = document.createElement("div");
				div.setAttribute("class", "autocomplete-div");

				// 添加弹出框表/字段图标
				let divIcon = ''
				if(data.type == 'table') {
					divIcon = document.createElement("i");
					divIcon.setAttribute("class", "el-icon-date");
					divIcon.style.color = 'blue'
				} else if(data.type == 'field') {
					divIcon = document.createElement("i");
					divIcon.setAttribute("class", "el-icon-film");
					divIcon.style.color = 'blue'
				} else {
					divIcon = document.createElement("i");
					divIcon.setAttribute("class", "el-icon-date");
					divIcon.style.color = 'blue'
				}

				let divText = document.createElement("span");
				divText.setAttribute("class", "autocomplete-name");
				divText.innerText = data.displayText;
				divText.style.display = 'inline-block'
				divText.style.overflow = 'hidden'
				divText.style.whiteSpace = 'nowrap'
				divText.style.textOverflow = 'ellipsis'
				divText.style.marginRight = '10px'

				let divInfo = document.createElement("span");
				divInfo.setAttribute("class", "autocomplete-hint");
				divInfo.innerText = data.displayInfo;
				divInfo.style.display = 'inline-block'
				divInfo.style.float = 'right'
				divInfo.style.color = 'gray'
				divInfo.style.maxWidth = '150px'
				divInfo.style.overflow = 'hidden'
				divInfo.style.whiteSpace = 'nowrap'
				divInfo.style.textOverflow = 'ellipsis'

				div.appendChild(divIcon);
				div.appendChild(divText);
				div.appendChild(divInfo);
				element.appendChild(div);
			},
			handleShowHint() {
				const hintList = [
					{
					name: "xiaohong",
					value: "xiaohong"
					},
					{
					name: "xiaozhang",
					value: [
						{
						name: "xiaoli",
						},
						{
						name: "xiaosun",
						},
					],
					},
				];
				const cmInstance = this.coder;
				console.log(cmInstance, 54);
				// 得到光标
				let cursor = cmInstance.getCursor();
				// 得到行内容
				let cursorLine = cmInstance.getLine(cursor.line);
				// 得到光标位置
				let end = cursor.ch;
				let start = end;
				const Two = `${cursorLine.charAt(start - 2)}${cursorLine.charAt(start - 1)}`;
				const One = `${cursorLine.charAt(start - 1)}`;
				let list = [];
				if (Two === "${") {
					hintList.forEach(e => {
					list.push(e.name)
					})
				} else if (One === ".") {
					let lastIndex = cursorLine.lastIndexOf('${', start)
					let key = cursorLine.substring(lastIndex + 2, start - 1)
					list = []
					hintList.forEach((e) => {
					if (e.name === key && lastIndex !== -1 && Object.prototype.toString.call(e.value) === '[object Array]') {
						e.value.forEach(el => {
						list.push(el.name)
						})
					}
					})
				}
				// 得到光标标识
				let token = cmInstance.getTokenAt(cursor);
				// console.log(cmInstance, cursor, cursorLine, end, token);
				return {
					list: list,
					from: { ch: end, line: cursor.line },
					to: { ch: token.end, line: cursor.line },
				};
			},
		}
	}
</script>

<style scoped>
	.code-editor {font-size: 14px;border: 1px solid #ddd;line-height: 150%;}
	.code-editor:deep(.CodeMirror)  {height: 100%;}

	.autocomplete-div{
		position:absolute;
		background: #ff990f;
		width: 100px;
		height: 30px;
	}
</style>
